package com.cmas.platform.service.impl;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import com.aidex.common.annotation.DataSource;
import com.aidex.common.config.AiDexConfig;
import com.aidex.common.constant.Constants;
import com.aidex.common.core.domain.R;
import com.aidex.common.enums.DataSourceType;
import com.aidex.common.exception.CustomException;
import com.aidex.common.utils.PageUtils;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.cmas.platform.common.annotation.OperatorDataScope;
import com.cmas.platform.domain.*;
import com.cmas.platform.domain.em.ApproveStatusEnum;
import com.cmas.platform.domain.em.NotificationTypeEnum;
import com.cmas.platform.mapper.*;
import com.cmas.platform.utils.ContentCheckUtil;
import com.cmas.platform.cache.ReLoadRedis;
import com.cmas.platform.vo.PostVo;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.aidex.common.utils.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cmas.platform.service.PostService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 帖子管理Service业务层处理
 *
 * @author su
 * @email 1218819874@qq.com
 * @date 2023-03-15
 */
@Service
public class PostServiceImpl extends ServiceImpl<PostMapper, Post> implements PostService {

    private static final Logger log = LoggerFactory.getLogger(PostServiceImpl.class);

    @Autowired
    private CommentMapper commentMapper;

    @Autowired
    private NotificationMapper notificationMapper;

    @Autowired
    private ApproveConfigMapper approveConfigMapper;

    @Autowired
    private ApproveRecordMapper approveRecordMapper;

    @Autowired
    private RegionMapper regionMapper;

    @Autowired
    private ReLoadRedis reLoadRedis;

    @Autowired
    private RabbitTemplate rabbitTemplate;


    /**
     * 查询帖子管理列表
     *
     * @param post 帖子管理
     * @return 帖子管理
     */
    @OperatorDataScope(useType = "1", fieldName = "regionId")
    @Override
    public List<PostVo> selectPostVoList(Post post) {
        PageUtils.startPage();
        QueryWrapper<Post> queryWrapper = setQueryWrapper(post);
        return baseMapper.selectPostList(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Post> addPost(Post post) {
        R<?> checkResult = checkSensitiveWord(post);
        R<Post> result = new R<>(checkResult.getCode(), checkResult.getMsg());
        if (R.isSuccess(checkResult)) {
            baseMapper.insert(post);
            result.setData(post);
            result.setMsg("操作成功");
            //发送消息
            sendMessage(Constants.POST_EXCHANGE, Constants.POST_QUEUE_ROUTING_KEY, post.getId());
        }
        return result;
    }

    public void sendMessage(String exchange, String key, String data) {
        rabbitTemplate.convertAndSend(exchange, key, data);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Post> updatePost(Post post) {
        R<?> checkResult = checkSensitiveWord(post);
        R<Post> result = new R<>(checkResult.getCode(), checkResult.getMsg());
        if (R.isSuccess(checkResult)) {
            baseMapper.updateById(post);
            result.setData(post);
            result.setMsg("操作成功");
            sendMessage(Constants.POST_EXCHANGE, Constants.POST_QUEUE_ROUTING_KEY, post.getId());
        }
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void approve(ApproveRecord approveRecord) {
        Post post = baseMapper.selectById(approveRecord.getItemId());
        approveRecord.setItemTableName(SqlHelper.table(Post.class).getTableName());
        approveRecord.setBeforeStatus(post.getStatus());
        if (approveRecord.getType().equals("0")) {
            post.setStatus(ApproveStatusEnum.ARTIFICIAL_PASS.getValue());
        } else if (approveRecord.getType().equals("1")) {
            post.setStatus(ApproveStatusEnum.ARTIFICIAL_REJECT.getValue());
        }
        approveRecordByPost(post, approveRecord);
    }

    /**
     * 通过地区审核配置进行审核(异步)
     *
     * @return
     */
    @Async
    @Override
    @DataSource(value = DataSourceType.SLAVE)
    public void approveByAsync(Post post) {
        setApprove(post);
    }

    /**
     * 通过地区审核配置进行审核(rabbitmq)
     *
     * @param postId
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = Constants.POST_QUEUE, durable = "true"),
            exchange = @Exchange(name = Constants.POST_EXCHANGE, type = ExchangeTypes.TOPIC),
            key = Constants.POST_QUEUE_ROUTING_KEY))
    @DataSource(value = DataSourceType.SLAVE)
    @Transactional(rollbackFor = Exception.class)
    public void approveByRabbitmq(String postId) {
        try {
            Post post = baseMapper.selectById(postId);
            setApprove(post);
        } catch (Exception e) {
            throw new CustomException("消息接受失败!");
        }

    }

    /**
     * 通过审核配置设置帖子
     *
     * @param post
     */
    public void setApprove(Post post) {
        ApproveConfig approveConfig = approveConfigMapper.selectOne(new QueryWrapper<ApproveConfig>().lambda()
                .eq(ApproveConfig::getItemId, post.getRegionId())
                .eq(ApproveConfig::getStatus, "0"));
        ApproveRecord approveRecord = new ApproveRecord();
        approveRecord.setItemId(post.getId());
        approveRecord.setItemTableName(SqlHelper.table(Post.class).getTableName());
        approveRecord.setBeforeStatus(post.getStatus());
        switch (approveConfig.getMethod()) {
            case "0":
                automaticApprove(post, approveRecord);
                break;
            case "1":
                artificial(post);
                break;
            case "2":
                if (automaticApprove(post, approveRecord)) {
                    artificial(post);
                }
                break;
        }
    }

    /**
     * 自动审核通过调用百度api
     *
     * @param post
     * @param approveRecord
     */
    public boolean automaticApprove(Post post, ApproveRecord approveRecord) {
        //调用百度API
        R<Integer> censorResult = ContentCheckUtil
                .getCommonTextCensorResult(post.getTitle() + post.getContent());
        int conclusionType = censorResult.getData();
        approveRecord.setReason(censorResult.getMsg());
        if (conclusionType == ContentCheckUtil.CENSOR_SUCCESS) {
            approveRecord.setType("0");
            post.setStatus(ApproveStatusEnum.AUTOMATIC_PASS.getValue());
            approveRecordByPost(post, approveRecord);
        } else if (conclusionType == ContentCheckUtil.CENSOR_FAIL) {
            post.setStatus(ApproveStatusEnum.AUTOMATIC_REJECT.getValue());
            approveRecord.setType("1");
            approveRecordByPost(post, approveRecord);
            return false;
        } else if (conclusionType == ContentCheckUtil.CENSOR_SUSPECT) {
            post.setStatus(ApproveStatusEnum.ARTIFICIAL_AUDIT.getValue());
            approveRecord.setType("1");
            approveRecordByPost(post, approveRecord);
        } else if (conclusionType == ContentCheckUtil.CENSOR_ERROR) {
            post.setStatus(ApproveStatusEnum.ARTIFICIAL_AUDIT.getValue());
            approveRecord.setType("1");
            approveRecordByPost(post, approveRecord);
            return false;
            //throw new CustomException("请求失败!");
        }
        return true;
    }

    /**
     * 人工审核方法
     *
     * @param post
     */
    public void artificial(Post post) {
        post.setStatus(ApproveStatusEnum.ARTIFICIAL_AUDIT.getValue());
        baseMapper.updateById(post);
    }

    /**
     * 通过帖子添加审核记录
     *
     * @param post
     * @param approveRecord
     */
    public void approveRecordByPost(Post post, ApproveRecord approveRecord) {
        baseMapper.updateById(post);
        approveRecord.setAfterStatus(post.getStatus());
        approveRecordMapper.insert(approveRecord);
        reLoadRedis.reloadPost(post);
        //地区通知
        sendRegionNotification(post);

    }

    public void sendRegionNotification(Post post) {
        String status = post.getStatus();
        if (status.equals(ApproveStatusEnum.AUTOMATIC_PASS.getValue()) ||
                status.equals(ApproveStatusEnum.ARTIFICIAL_PASS.getValue())) {
            Region region = regionMapper.selectById(post.getRegionId());
            if (region.getUserId().equals(post.getUserId())) {
                JSONObject message = new JSONObject();
                message.put("itemId", post.getId());
                message.put("regionId", post.getRegionId());
                message.put("content", post.getTitle());
                message.put("type", NotificationTypeEnum.REGION.getValue());
                sendMessage(Constants.NOTICE_EXCHANGE, Constants.NOTICE_QUEUE_ROUTING_KEY, message.toString());
            }
        }

    }

    /**
     * 敏感词检测
     *
     * @param post
     * @return
     */
    private R<?> checkSensitiveWord(Post post) {
        R<?> titleCheck = ContentCheckUtil.checkBySensitiveWord(post.getTitle());
        if (R.isError(titleCheck)) {
            return R.fail("标题" + titleCheck.getMsg());
        }
        R<?> contentCheck = ContentCheckUtil.checkBySensitiveWord(post.getContent());
        if (R.isError(contentCheck)) {
            return R.fail("内容" + contentCheck.getMsg());
        }
        return R.success("操作成功");
    }

    @Override
    public QueryWrapper<Post> setQueryWrapper(Post post) {
        QueryWrapper<Post> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(post.getId())) {
            queryWrapper.eq("cmas.post.id", post.getId());
        }
        if (StringUtils.isNotEmpty(post.getUserId())) {
            queryWrapper.eq("cmas.post.user_id", post.getUserId());
        }
        if (StringUtils.isNotEmpty(post.getRegionId())) {
            queryWrapper.eq("cmas.post.region_id", post.getRegionId());
        }
        if (StringUtils.isNotEmpty(post.getSectionId())) {
            queryWrapper.eq("cmas.post.section_id", post.getSectionId());
        }
        if (StringUtils.isNotEmpty(post.getTitle())) {
            queryWrapper.like("cmas.post.title", post.getTitle());
        }
        if (StringUtils.isNotEmpty(post.getContent())) {
            queryWrapper.like("cmas.post.content", post.getContent());
        }
        if (StringUtils.isNotEmpty(post.getAnonymity())) {
            queryWrapper.eq("cmas.post.anonymity", post.getAnonymity());
        }
        if (StringUtils.isNotEmpty(post.getType())) {
            queryWrapper.eq("cmas.post.type", post.getType());
        }
        if (StringUtils.isNotEmpty(post.getStatus())) {
            String[] statusList = post.getStatus().split(",");
            if (statusList.length > 1) {
                queryWrapper.in("cmas.post.status", statusList);
            } else {
                queryWrapper.eq("cmas.post.status", post.getStatus());
            }

        }
        return queryWrapper;
    }


    @Override
    public List<Post> selectPostList(Post post) {
        return baseMapper.selectList(setQueryWrapper(post));
    }

    /**
     * 批量删除帖子管理
     *
     * @param ids 需要删除的帖子管理ID
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deletePostByIds(String[] ids) {
        List<String> postIdList = Arrays.asList(ids);
        commentMapper.delete(new QueryWrapper<Comment>().lambda()
                .in(Comment::getPostId, ids));
        notificationMapper.delete(new QueryWrapper<Notification>()
                .lambda().in(Notification::getItemId, ids));
        //清除redis中数据
        List<Post> postList = baseMapper.selectBatchIds(postIdList);
        List<String> idsList = postList.stream().filter(item -> item.getStatus()
                        .equals(ApproveStatusEnum.AUTOMATIC_PASS.getValue())
                        || item.getStatus().equals(ApproveStatusEnum.ARTIFICIAL_PASS.getValue()))
                .map(Post::getId).collect(Collectors.toList());
        reLoadRedis.deletePost(idsList);
        return baseMapper.deleteBatchIds(postIdList);
    }

}
